'use strict';

const UniSecObj = require('uni-sec-check')

const uidObj = require('uni-id');
const uidPay = require('uni-pay');
const {
	Controller
} = require('uni-cloud-router');

const dbcmd = uniCloud.database().command;

module.exports = class OrderController extends Controller {

	// 创建订单 v2
	async createV2() {
		// 判断是否登录
		// 判断收货人是否存在
		// 判断下单来源 (1.从商品详情下单 2.从购物车下单)
		// 	判断商品是否存在
		// 	判断商品状态是否为 销售中
		// 	判断商品库存是否满足下单数
		// 	判断购物车商品是否存在
		// 	判断购物车商品状态是否为 销售中
		// 	判断购物车商品库存是否满足下单数
		// [新增]取付费会员商品会员价
		// 写入订单数据并记录分销数据（上级 上上级）
		// 根据订单设置,如果为下单成功后扣减库存,则扣减对应商品扣除
		// 写入订单详情数据
		// 写入订单支付数据
		// 写入订单日志

		let response = {
			code: 1,
			goods: {},
			goods_detail: {},
			goods_skus: []
		};

		const start = Date.now();
		const nowdate = start;

		let uid = '';
		let app_id
		let shop_id
		let alipay_shop_id
		let user = {
			openid: '',
			name: '',
			headimg: '',
			mobile: ''
		};
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid 
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
				if (userRes.userInfo.wx_openid) {
					user.openid = userRes.userInfo.wx_openid['mp-weixin'];
				} else {
					user.openid = userRes.userInfo.openid
				}
				user.name = userRes.userInfo.username || userRes.userInfo.nickname;
				user.headimg = userRes.userInfo.avatar;
				user.mobile = userRes.userInfo.mobile || '';
				shop_id = userRes.userInfo.shop_id
				app_id = userRes.userInfo.app_id
				let appletInfo = await this.service.applet.getAppletInfoById(app_id)
				user.alipay_id = appletInfo.alipay.auth_app_id
				alipay_shop_id = appletInfo.alipay.shop_id
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}
		if (!shop_id) {
			response.msg = '门店ID为空'
			return response;
		}
		/* if(!alipay_shop_id){
			response.msg = '支付宝门店ID为空'
			return response;
		} */
		const {
			cart_ids,
			sharemid,
			goods_id,
			goods_num,
			goods_sku_id,
			order_coupon_id,
			addr_id,
			order_from,
			order_desc,
			seckill_id, // 秒杀ID
			group_id, // 团购ID
			group_chief_id, // 团长ID
			self_pick
		} = this.ctx.data;

		const memberRes = await this.db.collection('wmzmall-member').doc(uid).get();

		let [memberData = {}] = memberRes.data;
		if (!(memberData && memberData._id)) {
			response.msg = '当前用户数据异常，请重新登录后下单';
			return response;
		}

		if (!memberData.myfxs_uid && !memberData.bind_has && sharemid && sharemid != uid) {
			// 修改下单者的 分销商
			console.log('修改下单者的 分销商', memberData, sharemid);

			// 获得 sharemid 的上级
			let sharemid2 = '';
			let shareData2 = {};

			const shareRes = await this.db.collection('wmzmall-member').doc(sharemid)
				.field({
					myfxs_uid: true
				}).get();
			const [shareUser] = shareRes.data;
			if (shareUser && shareUser.myfxs_uid) {
				// 上上级
				sharemid2 = shareUser.myfxs_uid
			}

			if (sharemid2) {
				shareData2 = {
					myfxs_uid2: sharemid2,
					myfxs_time2: nowdate,
					myfxs_source2: 'order',
					myfxs_order_cnt2: 0,
					myfxs_profit_amount2: 0,
				};
			}

			await this.db.collection('wmzmall-member').doc(uid).update({
				myfxs_uid: sharemid,
				myfxs_time: nowdate,
				myfxs_source: 'order',
				myfxs_order_cnt: 0,
				myfxs_profit_amount: 0,

				bind_has: 1,

				...shareData2
			});
			await this.db.collection('wmzmall-distributor').doc(sharemid).update({
				fxs_member_cnt: this.db.command.inc(1)
			});

			// 修改上级
			await this.db.collection('wmzmall-member').doc(sharemid).update({
				bind_has: 1
			});

			if (sharemid2) {
				await this.db.collection('wmzmall-distributor').doc(sharemid2).update({
					fxs_member_cnt: this.db.command.inc(1)
				});

				// 修改上上级
				await this.db.collection('wmzmall-member').doc(sharemid2).update({
					bind_has: 1
				});
			}

			memberData.myfxs_uid = sharemid;
			memberData.myfxs_uid2 = sharemid2;
		}

		// 已付费有效期内的会员
		memberData.vip = memberData.is_plus === '付费会员' && memberData.plus_time >= Date.now();
		let addr = {}
		if (!self_pick) {
			const addrRes = await this.db.collection('wmzmall-member-address').doc(addr_id).get();
			if (!(addrRes && addrRes.data.length === 1)) {
				response.msg = '请选择收货人';
				return response;
			}
			addr = addrRes.data[0];
			if (addr.create_uid != uid) {
				response.msg = '收货人与当前账号不一致';
				return response;
			}
		}

		let seckillData = {};
		let groupData = {};
		let groupChiefData = {};

		// 拼团价格
		let group_price = 0;

		let goods = [];
		let goodsData = {};
		let preOrder = {};

		// 购物车 ID 集合
		let goodsCartIds = [];
		if (goods_id) {
			// 从商品详情页下单
			const goodsRes = await this.db.collection('wmzmall-goods').doc(goods_id).field({
				cids: false,
				stock_wh_num: false,
				sold_out_time: false,
				collect_cnt: false,
				collect: false,
				share_cnt: false,
				share: false,
				visit_cnt: false,
				visit: false,
				search_tags: false,
				create_time: false,
				create_uid: false,
				create_uname: false,
				last_modify_time: false,
				last_modify_uid: false,
				last_modify_uname: false
			}).get();
			if (!(goodsRes.data && goodsRes.data.length == 1)) {
				response.msg = '当前下单商品不存在';
				return response;
			}
			[goodsData] = goodsRes.data;
			const goodsState = goodsData.state;
			if (goodsState != '销售中') {
				switch (goodsState) {
					case '待审核':
						response.msg = `当前商品未开售`;
						break;
					case '已下架':
					default:
						response.msg = `当前商品${goodsState}`;
						break;
				}
				return response;
			}

			// 下单数量
			goodsData.goods_num = goods_num || 1;

			if (goods_sku_id) {
				// 商品存在 sku
				let skuRes = await this.db.collection('wmzmall-goods-sku').doc(goods_sku_id).get();
				if (skuRes && skuRes.data.length == 1) {
					let goodsSku = skuRes.data[0];
					// 存在 sku 修改商品价格、库存
					goodsData.stock_num = goodsSku.stock_num;
					goodsData.price = goodsSku.price;
					goodsData.vip_price = goodsSku.vip_price;
					goodsData.market_price = goodsSku.market_price;
					goodsData.sku = goodsSku.goods_sku;
					goodsData.sku_id = goodsSku._id;
					goodsData.sku_name = [goodsSku.sku1_spec, goodsSku.sku2_spec, goodsSku.sku3_spec, goodsSku
						.sku4_spec
					].filter(s => s).join(' & ');
					goodsData.sku_img = goodsSku.img;
					goodsData.sku_price = goodsSku.price;
					goodsData.sku_market_price = goodsSku.market_price;
				}
			}

			// 特价：限时拼团、限时秒杀的为特价商品
			goodsData.tejia = false;

			if (seckill_id) {
				seckillData = await this.service.marketing.getSeckill(seckill_id);
				// 验证当前商品是否存在活动中
				if (seckillData && !seckillData.goods_ids.find(x => x == goods_id)) {
					response.msg = `秒杀活动中不存在当前下单商品`;
					return response;
				}
				// 下单商品
				seckillData.goods_obj = seckillData.goods_objs.find(x => x._id == goods_id);
				goodsData.price_tag = '秒杀价';
				goodsData.tejia = true;
				// 修改为秒杀价、秒杀库存、商品原价
				goodsData.price = seckillData.goods_obj.price;
				goodsData.stock_num = seckillData.goods_obj.stock_num;
				goodsData.market_price = goodsData.price;

				if (seckillData.goods_obj.limit && goodsData.goods_num > seckillData.goods_obj.limit) {
					response.msg = `下单数量×${goodsData.goods_num}，超过限购量×${seckillData.goods_obj.limit}`;
					return response;
				}
			}
			if (group_id) {
				// !group_chief_id 不存在团长，验证活动有效性
				// 则参团订单不验证
				groupData = await this.service.marketing.getGroup(group_id, !group_chief_id);
				// 验证当前商品是否存在活动中
				if (groupData && groupData.goods_id !== goods_id) {
					response.msg = `拼团活动中不存在当前下单商品`;
					return response;
				}

				if (group_chief_id) {
					// 判断团长是否存在
					groupChiefData = await this.service.marketing.getGroupChief(group_chief_id);
					if (groupChiefData && groupChiefData.group_id !== group_id) {
						response.msg = `当前参团与拼团活动不匹配`;
						return response;
					}

					const groupMemberIdx = groupChiefData.group_members.findIndex(x => x.uid == uid);
					if (groupMemberIdx !== -1) {
						response.msg = `您已参团，无需重复参与`;
						return response;
					}

					// 判断参团人员是否已满
					if (groupData.group_num - groupChiefData.group_members.length == 0) {
						response.msg = `当前拼单已满员，请发起新的拼团`;
						return response;
					}
				}

				goodsData.price_tag = '拼团价';
				goodsData.tejia = true;
				// 修改为拼团价、拼团库存、商品原价
				goodsData.price = groupData.goods_price;
				goodsData.stock_num = groupData.goods_obj.stock_num;
				goodsData.market_price = goodsData.price;

				// 拼团限购数量为1
				goodsData.goods_num = 1;
				// 拼团价
				group_price = groupData.goods_price;
			}

			// 会员购买会员价商品
			if (memberData.vip && goodsData.is_vip === '是' && !goodsData.tejia) {
				goodsData.price_tag = '会员价';
			}

			// 判断库存是否满足下单数
			if (goodsData.stock_num < goodsData.goods_num) {
				response.msg = `当前商品库存数不足`;
				return response;
			}

			// 当前下单商品
			goods.push(goodsData);
		} else if (cart_ids && cart_ids.length > 0) {
			// 从购物车下单
			let goodsCartRes = await this.db.collection('wmzmall-goods-cart').where({
				create_uid: uid,
				_id: dbcmd.in(cart_ids)
			}).get();
			if (!(goodsCartRes && goodsCartRes.data.length > 0)) {
				response.msg = '当前购物车不存在';
				return response;
			}
			let goodsCarts = goodsCartRes.data;
			goodsCartIds = goodsCarts.map(x => x._id);

			let goodsIds = goodsCarts.map(x => x.goods);
			let goodsSkuIds = goodsCarts.filter(x => x.goods_sku).map(x => x.goods_sku);

			let goodsRes = await this.db.collection('wmzmall-goods').where({
				_id: dbcmd.in(goodsIds),
				state: '销售中'
			}).get();
			if (!(goodsRes && goodsRes.data.length)) {
				response.msg = '当前购物车商品不存在';
				return response;
			}
			let goodsSkus = [];
			let goodsDatas = goodsRes.data;
			if (goodsSkuIds && goodsSkuIds.length) {
				let skuRes = await this.db.collection('wmzmall-goods-sku').where({
					goods_id: dbcmd.in(goodsIds),
					goods_sku: dbcmd.in(goodsSkuIds)
				}).get();
				if (skuRes.data && skuRes.data.length) {
					goodsSkus = skuRes.data;
				}

				if (skuRes.data.length !== goodsSkuIds.length) {
					response.msg = `当前下单的商品存在已失效SKU`;
					return response;
				}
			}

			goodsCarts.forEach((x, idx) => {
				// 进行深拷贝，防止同一sku产品 堆属性引用值 数据
				goodsData = JSON.parse(JSON.stringify(goodsDatas.find(g => g._id == x.goods)));
				// 购物车商品数量
				goodsData.goods_num = x.goods_num;

				let goodsSku = goodsSkus.find(g => g.goods_sku == x.goods_sku && g.goods_id == x.goods);

				if (goodsSku && goodsSku._id) {
					goodsData.stock_num = goodsSku.stock_num;
					goodsData.price = goodsSku.price;
					goodsData.vip_price = goodsSku.vip_price;
					goodsData.market_price = goodsSku.market_price;
					goodsData.sku = goodsSku.goods_sku;
					goodsData.sku_id = goodsSku._id;
					goodsData.sku_name = [goodsSku.sku1_spec, goodsSku.sku2_spec, goodsSku.sku3_spec,
						goodsSku.sku4_spec
					].filter(s => s).join(' & ');
					goodsData.sku_img = goodsSku.img;
					goodsData.sku_price = goodsSku.price;
					goodsData.sku_market_price = goodsSku.market_price;
				}

				// 判断库存是否满足下单数
				if (goodsData.stock_num < goodsData.goods_num) {
					response.msg = `当前商品库存数不足`;
					return response;
				}

				// 价格标签
				goodsData.price_tag = '';
				// 非特价商品
				goodsData.tejia = false;

				// 会员购买会员价商品
				if (memberData.vip && goodsData.is_vip === '是' && !goodsData.tejia) {
					goodsData.price_tag = '会员价';
				}

				// 下单商品
				goods.push(goodsData);
			});
		}

		if (goods.length <= 0) {
			response.msg = `下单商品不存在`;
			return response;
		}
		const utc8date = this.service.utils.toDateUTC8(Date.now());
		let order = {
			order_id: Date.now() + (Math.round(Math.random() * 1000000) + '').padStart(6, '0'),
			order_member_openid: user.openid,
			order_member_name: memberData.member_name || memberData.member_nickname,
			order_member_headimg: memberData.member_headimg,
			order_member_mobile: memberData.member_mobile,
			order_consignee: addr.consignee,
			order_consignee_tel: addr.mobile,
			order_consignee_addr: addr.address,
			order_consignee_addr_detail: addr.addr_detail,
			order_consignee_province_name: addr.province_name,
			order_consignee_city_name: addr.city_name,
			order_consignee_district_name: addr.area_name,
			order_express: '',
			order_express_no: '',
			order_pay_state: '待付款',
			order_total_money: 0,
			order_total_cnt: goods.length,
			order_goods_cnt: 0,
			order_sku_cnt: 0,
			order_discount: 0,
			order_tax: 0,
			order_actural_paid: 0,
			order_from: order_from,
			order_type: '发货订单',
			order_way: '小程序',
			order_info: '',
			remark: order_desc,
			// 分销
			is_fxs: '否',
			is_settlement: '否',
			order_fxs_uid: memberData.myfxs_uid,
			order_fxs_amount: 0,
			order_fxs_uid2: memberData.myfxs_uid2,
			order_fxs_amount2: 0,
			order_share_member_id: sharemid,
			state: '待付款',
			yy_mm: this.service.utils.formatdate(utc8date, 'yyyy年MM月'),
			yy_mm_dd: this.service.utils.formatdate(utc8date, 'yyyy年MM月dd日'),
			is_delete: 0,
			create_uid: uid,
			create_time: nowdate,
			create_time_format: this.service.utils.formatdate(utc8date, 'yyyy-MM-dd hh:mm:ss'),
			last_modify_time: nowdate,
			app_id: app_id,
			shop_id: shop_id,
			alipay_id: user.alipay_id,
			wechat_id: user.wechat_id,
			alipay_shop_id: alipay_shop_id,
			// 到期时间
			order_expire_time: 0,
			// 秒杀ID
			seckill_id: seckill_id,
			// 拼团ID
			group_id: group_id,
			// 团长ID
			group_chief_id: group_chief_id,
			self_pick: self_pick
		};

		// 下单所得积分
		let integral_total = 0;
		// 已省金额
		let economize_amount = 0;

		let order_detail = {};
		let order_details = [];
		goods.forEach(x => {
			economize_amount = 0;
			// vip付费会员
			if (memberData.vip) {
				// 非特价的会员商品
				// 特价：限时拼团、限时秒杀的为特价商品
				if (x.is_vip === '是' && !x.tejia) {
					x.market_price = x.price;
					x.price = x.vip_price;

					economize_amount = x.market_price - x.price;
				}
			}

			order_detail = {
				order_id: order.order_id,
				goods_id: x._id,
				goods_name: x.name,
				goods_name_pw: x.name_pw,
				goods_img: x.img,
				goods_imgs: x.imgs,
				goods_video: x.video,
				goods_num: x.goods_num,
				goods_price: x.price,
				goods_market_price: x.market_price,

				// 价格标签
				goods_price_tag: x.price_tag || '',
				// 特价商品
				goods_tejia: x.tejia || false,

				goods_type: x.goods_type || '',
				goods_sku: x.sku || '',
				goods_sku_name: x.sku_name || '',
				goods_sku_img: x.sku_img || x.img,
				goods_sku_id: x.sku_id || '',
				economize_amount: economize_amount,
				is_vip: memberData.vip ? x.is_vip : '',
				is_fxs: x.is_fxs,
				// 上级
				rebate_ratio: x.rebate_ratio,
				fxs_amount: 0,
				// 上上级
				rebate_ratio2: x.rebate_ratio2,
				fxs_amount2: 0,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate,
				app_id: app_id,
				shop_id: shop_id
			};

			if (x.tejia) {
				// 秒杀ID
				order_detail.seckill_id = seckill_id;
				// 拼团ID
				order_detail.group_id = group_id;
			}

			if (x.is_fxs == '是') {
				order.is_fxs = '是';
			}

			order.order_sku_cnt += x.goods_num;
			order.order_goods_cnt += x.goods_num;
			order.order_total_money += x.price * x.goods_num;
			order.order_actural_paid += x.price * x.goods_num;
			// 订单支付标题
			order.order_info = x.name;

			order_details.push(order_detail);
		});

		// 优惠券下单
		let coupon = null;
		if (order_coupon_id) {
			order.order_coupon_id = order_coupon_id;
			const couponRes = await this.db.collection('wmzmall-marketing-coupon').doc(order_coupon_id).get();

			if (!(couponRes.data && couponRes.data.length === 1)) {
				response.msg = '使用的优惠券不存在';
				return response;
			}
			coupon = couponRes.data[0];
			if (coupon.member_id !== uid) {
				response.msg = '请选择本人的优惠券';
				return response;
			}
			if (coupon.is_delete !== 0) {
				response.msg = '使用的优惠券已作废';
				return response;
			}
			if (coupon.state !== '已领取') {
				response.msg = `使用的优惠券【${coupon.state}】`;
				return response;
			}
			if (coupon.end_time < Date.now()) {
				response.msg = `使用的优惠券-已过期`;
				return response;
			}
			if (coupon.order_amount > 0 && coupon.order_amount * 100 > order.order_actural_paid) {
				response.msg = `实际支付金额满[${coupon.order_amount}]可使用优惠券`;
				return response;
			}

			// todo 判断优惠券使用范围

			switch (coupon.type) {
				case '满减':
					order.order_discount = coupon.price;
					order.order_actural_paid -= coupon.price;
					break;
				case '折扣':
					order.order_discount = order.order_actural_paid - order.order_actural_paid * coupon.price;
					order.order_actural_paid *= coupon.price / 100;
					break;
			}
			// 使用的优惠券
			order.order_coupon = coupon;
		}
		if (memberData.vip_price_discount) {
			order.order_discount = (order.order_actural_paid - order.order_actural_paid * memberData
				.vip_price_discount) / 100;
			order.order_actural_paid = order.order_actural_paid - order.order_discount * 100;
		}
		// 处理订单实际付款金额，精度丢失问题
		order.order_actural_paid = parseInt(order.order_actural_paid);



		// 计算分销佣金
		order_details.forEach(x => {
			if (x.is_fxs == '是') {
				let discount_ratio = 1;
				// 判断付款金额是否存在优惠
				if (order.order_actural_paid !== order.order_total_money) {
					discount_ratio = this.format_float(order.order_actural_paid / order
						.order_total_money);
				}

				// format_float float 格式化，防止 js 精度丢失
				if (Boolean(memberData.myfxs_uid)) {
					// 上级返利金额
					x.fxs_amount = this.format_float(x.goods_price * x.goods_num * discount_ratio * (x
						.rebate_ratio / 100));
					order.order_fxs_amount += x.fxs_amount;
				}
				if (Boolean(memberData.myfxs_uid2)) {
					// 上上级返利金额
					x.fxs_amount2 = this.format_float(x.goods_price * x.goods_num * discount_ratio * (x
						.rebate_ratio2 / 100));
					order.order_fxs_amount2 += x.fxs_amount2;
				}
			}
		})

		if (order.order_actural_paid > 0) {
			// 获取会员设置项
			const memberParameter = this.db.collection('wmzmall-member-parameter').where({
				shop_id: shop_id
			}).field({
				desc: false,
				vip_desc: false
			}).get();
			// 获取积分设置项
			const integralParameter = this.db.collection('wmzmall-integral-parameter').where({
				shop_id: shop_id
			}).field({
				integral_desc: false
			}).get();

			const datas = await Promise.all([memberParameter, integralParameter]);

			const memberParameterRes = datas[0];
			const integralParameterRes = datas[1];

			const member_setting = memberParameterRes.data && memberParameterRes.data[0];
			const integral_setting = integralParameterRes.data && integralParameterRes.data[0];

			// 下单返积分
			if (integral_setting && integral_setting.return_integral_ratio > 0) {
				integral_total = parseInt(order.order_actural_paid * (integral_setting.return_integral_ratio /
					100));
			}
			if (memberData.vip && member_setting && member_setting.vip_integral_mul > 0 && integral_total > 0) {
				integral_total *= member_setting.vip_integral_mul;
			}
			order.order_return_integral = integral_total;
		} else {
			order.order_actural_paid = 0;
		}

		// 读取订单配置
		const orderConfig = await this.service.utils.getOrderConfig();

		// 开启事务
		const dbtran = await this.db.startTransaction();

		try {

			if (order.order_actural_paid <= 0) {
				// 修改订单为已付款待发货
				order.state = '待发货';
				order.order_pay_state = '已付款';
			} else {
				// 待付款 超过60分钟未付款，自动取消订单
				order.order_expire_time = Date.now() + (orderConfig.overdue_minute_cancel_order || 60) * 60 *
					1000;
			}

			// 下单后扣减库存
			if (orderConfig.stock_ded_type == 1) {
				// 扣减库存
				order.order_ded_stock = 1;
			}

			const orderRes = await dbtran.collection('wmzmall-order').add(order);
			console.log('orderRes', orderRes);

			if (!(orderRes && orderRes.id)) {
				// 回滚事务
				await dbtran.rollback();

				response.msg = `订单创建失败`;
				uniCloud.logger.error(`订单创建失败`, order);
				console.log(`订单创建失败`, order);
				return response;
			}

			if (order_details.length === 1) {
				await dbtran.collection('wmzmall-order-detail').add(order_details[0]);
			}

			let order_log = {
				order_id: order.order_id,
				log_type: '创建订单',
				current_state: '待付款',
				prev_state: '待付款',
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			};
			await dbtran.collection('wmzmall-order-log').add(order_log);

			if (order.order_actural_paid <= 0) {
				// 订单日志 待发货
				order_log.log_type = '订单支付';
				order_log.current_state = '待发货';
				order_log.prev_state = '待付款';
				await dbtran.collection('wmzmall-order-log').add(order_log);
			}

			// 已使用优惠券
			if (order_coupon_id && coupon && coupon._id) {
				await dbtran.collection('wmzmall-marketing-coupon')
					.doc(order_coupon_id)
					.update({
						last_modify_time: nowdate,
						last_modify_uid: uid,

						order_id: order.order_id,
						version: dbcmd.inc(1),

						state: "已使用"
					});
				await dbtran.collection('wmzmall-marketing-coupon-rule')
					.doc(coupon.coupon_id)
					.update({
						use_num: dbcmd.inc(1),
						version: dbcmd.inc(1)
					});
				await dbtran.collection('wmzmall-member')
					.doc(uid)
					.update({
						member_coupon_cnt: dbcmd.inc(-1)
					});
			}

			let __group_chief_id = group_chief_id;
			if (group_id) {
				const groupMember = {
					order_id: order.order_id,
					uid: order.create_uid,
					// 参团人名称进行脱敏处理
					uname: this.service.utils.desz(order.order_member_name),
					uheadimg: order.order_member_headimg,
					state: '待付款'
				};
				if (group_chief_id) {
					// 增加参团数据
					await dbtran.collection('wmzmall-market-groupbuy-member').doc(group_chief_id).update({
						group_members: this.db.command.push(groupMember),
						last_modify_time: nowdate,
						last_modify_uid: uid,
						last_modify_uname: order.order_member_name
					});
				} else {
					__group_chief_id = uid + '_' + order.order_id;
					// 创建开团数据
					await dbtran.collection('wmzmall-market-groupbuy-member').add({
						_id: __group_chief_id,
						goods_id: goods_id,
						goods_price: group_price,
						group_id: group_id,
						group_num: groupData.group_num,
						expire_time: 0,
						group_members: [groupMember],
						group_member_pay_cnt: 0,
						member_uid: uid,
						member_name: this.service.utils.desz(order.order_member_name),
						member_openid: order.order_member_openid,
						member_headimg: order.order_member_headimg,
						group_chief_id: __group_chief_id,
						order_id: order.order_id,
						state: '待付款',
						remark: '',
						version: 1,
						is_delete: 0,
						create_time: nowdate,
						create_uid: uid,
						create_uname: order.order_member_name
					});
				}
			}

			response.code = 0;
			response.datas = {
				order_id: order.order_id,
				money: order.order_actural_paid,
				vip: memberData.vip
			};
			if (__group_chief_id) {
				response.datas.group_chief_id = __group_chief_id;
			}

			// 提交事务
			await dbtran.commit();

			// 可改造为循环，使用事务添加
			// 事务不支持一次性添加多条数据
			if (order_details.length > 1) {
				await this.db.collection('wmzmall-order-detail').add(order_details);
			}

			// 下单后扣减订单库存
			if (orderConfig.stock_ded_type == 1) {
				for (let i = 0; i < order_details.length; i++) {
					let x = order_details[i];

					// 扣减库存
					await this.db.collection('wmzmall-goods')
						.where({
							_id: x.goods_id,
							stock_num: dbcmd.gte(x.goods_num)
						})
						.update({
							stock_num: dbcmd.inc(-x.goods_num),
							sale_cnt: dbcmd.inc(x.goods_num)
						});
					// 扣减SKU库存
					if (x.goods_sku) {
						await this.db.collection('wmzmall-goods-sku')
							.where({
								goods_id: x.goods_id,
								goods_sku: x.goods_sku,
								stock_num: dbcmd.gte(x.goods_num)
							})
							.update({
								stock_num: dbcmd.inc(-x.goods_num),
								sale_cnt: dbcmd.inc(x.goods_num)
							});
					}
				}
			}

			// 删除购物车数据
			if (goodsCartIds.length > 0) {
				await this.db.collection('wmzmall-goods-cart').where({
					_id: dbcmd.in(goodsCartIds)
				}).remove();
			}

		} catch (e) {
			// 回滚事务
			await dbtran.rollback();

			response.code = 500;
			response.msg = e.message;

			// 记录日志
			uniCloud.logger.error(e);
			console.log('order/create catch', e);
		}

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.duration = `耗时：${end - start}ms`;

		return response;
	}
	// float 格式化，防止 js 精度丢失
	format_float(number) {
		number = parseInt(number * 100);

		return number / 100;
	}

	// 订单详情
	async detail() {
		let response = {
			code: 1,
			order: {},
			order_detail: []
		};

		const start = Date.now();
		const nowdate = start;
		const {
			order_id
		} = this.ctx.data;
		let uid = '';
		let shop_id
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
				shop_id = userRes.userInfo.shop_id
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}

		// 订单时间
		let order_time = 0;
		// 配置时间
		let order_config_time = 0;

		const order = this.db.collection('wmzmall-order').where({
			is_delete: 0,
			order_id: order_id,
			create_uid: uid
		}).get();
		const order_detail = this.db.collection('wmzmall-order-detail').where({
			order_id: order_id
		}).get();
		const orderConfigRes = this.db.collection('wmzmall-order-parameter').where({
			shop_id: shop_id
		}).get();

		const datas = await Promise.all([order, order_detail, orderConfigRes]);

		[response.order] = datas[0] && datas[0].data;
		response.order_detail = datas[1] && datas[1].data;

		if (!(response.order && response.order._id)) {
			response.msg = `订单[${order_id}]不存在`;
			return response;
		}

		// 订单配置
		const [orderConfig] = datas[2] && datas[2].data;
		response.order_config = orderConfig;

		try {
			switch (response.order.state) {
				case '待付款':
					response.time_remaining = parseInt((response.order.order_expire_time - Date.now()) / 1000);

					if (response.time_remaining <= 0) {
						// 自动取消订单
						await this.__cancelOrder(uid, response.order, '超时自动取消');
						response.order.state = '已取消';
					}
					break;
				case '待成团':
					response.time_remaining = parseInt((response.order.order_expire_time - Date.now()) / 1000);

					if (response.time_remaining <= 0) {
						// todo 判断是否已成团

						// 自动取消拼团订单
						await this.__cancelOrder(uid, response.order, '超时自动取消', 2);
					}
					break;
				case '待发货':
					// 成团时间 || 付款时间
					order_time = response.order.order_group_time || response.order.order_pay_time;
					// 付款后，预计3天内发货
					order_config_time = (orderConfig.predict_day_deliver || 3) * 24 * 60 * 60;
					// 待发货剩余秒数 = 待发货(秒) - 付款时间到现在(秒)
					response.time_remaining = parseInt(order_config_time - (Date.now() - order_time) / 1000);

					break;
				case '待收货':
					// 发货后，超过 7天自动收货
					order_config_time = (orderConfig.overdue_day_receiving || 7) * 24 * 60 * 60;
					// 待收货剩余秒数 = 待收货(秒) - 发货时间到现在(秒)
					response.time_remaining = parseInt(order_config_time - (Date.now() - response.order
						.deliver_time) / 1000);

					if (response.time_remaining <= 0) {
						// todo 自动确认收货

					}
					break;
			}

		} catch (e) {
			response.msg = e.message;
		}

		if (response.order && response.order.group_id) {
			response.group = await this.service.marketing.getGroup(response.order.group_id, false);
			if (response.order.group_chief_id) {
				response.group_chief = await this.service.marketing.getGroupChief(response.order.group_chief_id,
					false);
			} else {
				response.group_chief = await this.service.marketing.getGroupChiefByOrder(response.order
					.order_id, false);
			}

			// 判断是否在拼单中
			if (!response.group_chief.group_members.find(x => x.uid == uid)) {
				delete response.group;
				delete response.group_chief;
			}
		}

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}

	// 订单列表
	async list() {
		let response = {
			code: 1,
			order: []
		};

		const start = Date.now();
		const {
			page,
			rows,
			state
		} = this.ctx.data;
		let uid = '';
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}
		let where_obj = {
			is_delete: 0,
			create_uid: uid
		};
		if (state && state != '全部') {
			where_obj.state = state;
		}

		let orderRes = await this.db.collection('wmzmall-order')
			.where(where_obj)
			.orderBy('create_time', 'desc')
			.skip((page - 1) * rows)
			.limit(rows)
			.get();

		let datas = [];
		const ids = orderRes.data.map(x => x.order_id);

		let orderDetailsRes = await this.db.collection('wmzmall-order-detail').where({
			order_id: this.db.command.in(ids)
		}).get();

		orderRes.data.forEach(x => {
			datas.push({
				order: x,
				order_detail: orderDetailsRes.data.filter(d => d.order_id == x.order_id)
			})
		});
		response.datas = datas;

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}
	// 取消订单
	async cancel() {
		let response = {
			code: 1,
		};
		const start = Date.now();
		const nowdate = start;
		const {
			order_id,
			state
		} = this.ctx.data;

		let uid = '';
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
			}
		}

		const orderRes = await this.db.collection('wmzmall-order').where({
				order_id: order_id
			})
			.field({
				state: true,
				group_id: true,
				group_chief_id: true,

				order_id: true,
				create_uid: true,
				order_member_name: true,
				order_expire_time: true,

				order_coupon_id: true,
				order_ded_stock: true
			})
			.limit(1)
			.get();

		const [order] = orderRes.data;

		if (!(order && order._id)) {
			response.msg = '订单不存在';
			return response;
		}

		if (!['待付款', '待成团'].includes(order.state)) {
			response.msg = `当前订单[${order.state}]`;
			return response;
		}

		// 取消订单
		response.datas = await this.__cancelOrder(uid, order, '手动取消订单');

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}
	// 取消订单服务
	async __cancelOrder(uid, order, remark) {
		const nowdate = Date.now();
		const state = '已取消';

		let groupData = {};
		let groupChiefData = {};
		let groupMemberIdx = -1;
		let groupChiefMemberIdx = -1;
		if (order.group_id) {
			groupData = await this.service.marketing.getGroup(order.group_id, false);
			// 当前参团人下标
			groupMemberIdx = groupData.group_members.findIndex(x => x.uid == order.create_uid);

			if (order.group_chief_id) {
				// 参团订单
				groupChiefData = await this.service.marketing.getGroupChief(order.group_chief_id, false);
				// 当前团成员下标
				groupChiefMemberIdx = groupChiefData.group_members.findIndex(x => x.order_id == order.order_id);
			} else {
				// 开团订单
				groupChiefData = await this.service.marketing.getGroupChiefByOrder(order.order_id, false);

				// 判断是否已有成员参团
				if (groupChiefData.group_members.length > 1) {
					this.throw('已有成员加团，禁止取消');
				}
			}
		}

		const orderRes = await this.db.collection('wmzmall-order')
			.doc(order._id)
			.update({
				state: state,

				last_modify_time: nowdate,
				last_modify_uid: uid,
			})

		if (orderRes && orderRes.updated) {
			// 取消成功
			// 判断是否为拼团订单
			if (groupData && groupData._id) {
				if (order.group_chief_id) {
					// 参团订单
					// 退出团成员
					await this.db.collection('wmzmall-market-groupbuy-member').doc(groupChiefData._id)
						.update({
							group_members: this.db.command.pull({
								uid: order.create_uid
							})
						});
				} else {
					// 开团订单
					await this.db.collection('wmzmall-market-groupbuy-member').doc(groupChiefData._id)
						.update({
							state: '已取消'
						});
				}

				if (order.state == '待成团') {
					// 团订单-1，团成员-1，干掉参团人
					const groupUpdateObj = {};

					if (groupMemberIdx != -1) {
						groupUpdateObj.group_members = this.db.command.pull({
							uid: uid
						});
					}

					// 团成员-1
					if (groupData.group_member_cnt) {
						groupUpdateObj.group_member_cnt = this.db.command.inc(-1)
					}
					// 团订单-1
					if (groupData.group_order_cnt) {
						groupUpdateObj.group_order_cnt = this.db.command.inc(-1)
					}

					if (Object.keys(groupUpdateObj).length) {
						await this.db.collection('wmzmall-market-groupbuy').doc(groupData._id).update(
							groupUpdateObj);
					}

					// todo 判断是手动退款还是自动退款

				}
			}

			// 写入日志
			await this.db.collection('wmzmall-order-log').add({
				order_id: order.order_id,
				log_type: '取消订单',
				current_state: state,
				prev_state: '待付款',
				remark: remark || '取消订单',
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			});

			/**
			 * 取消订单
			 * 
			 * 1. 判断是否需要释放库存
			 * 2. 判断是否需要释放优惠券
			 */
			// 释放库存
			if (order.order_ded_stock) {
				// 查询订单详情
				const orderDetailRes = await this.db.collection('wmzmall-order-detail').where({
						order_id: order.order_id
					})
					.field({
						goods_id: true,
						goods_sku: true,
						goods_num: true,
					})
					.get();

				for (let i = 0; i < orderDetailRes.data.length; i++) {
					let x = orderDetailRes.data[i];

					// 释放库存
					await this.db.collection('wmzmall-goods')
						.doc(x.goods_id)
						.update({
							stock_num: dbcmd.inc(x.goods_num),
							sale_cnt: dbcmd.inc(-x.goods_num)
						});
					// 释放SKU库存
					if (x.goods_sku) {
						await this.db.collection('wmzmall-goods-sku')
							.where({
								goods_id: x.goods_id,
								goods_sku: x.goods_sku
							})
							.update({
								stock_num: dbcmd.inc(x.goods_num),
								sale_cnt: dbcmd.inc(-x.goods_num)
							});
					}
				}
			}

			// 释放优惠券
			if (order.order_coupon_id) {
				// 获取对应的优惠券数据
				const couponRes = await this.db.collection('wmzmall-marketing-coupon')
					.doc(order.order_coupon_id)
					.get();
				if (couponRes.data && couponRes.data.length) {
					const [coupon] = couponRes.data;

					await this.db.collection('wmzmall-marketing-coupon')
						.doc(coupon._id)
						.update({
							last_modify_time: nowdate,
							last_modify_uid: uid,

							version: dbcmd.inc(1),

							state: "已领取"
						});

					await this.db.collection('wmzmall-marketing-coupon-rule')
						.doc(coupon.coupon_id)
						.update({
							use_num: dbcmd.inc(-1),
							version: dbcmd.inc(1)
						});

					await this.db.collection('wmzmall-member')
						.doc(coupon.member_id)
						.update({
							member_coupon_cnt: dbcmd.inc(1)
						});
				}
			}

		}

		return orderRes;
	}

	// 已收货
	//   结算分销订单（测试阶段，实际应为确认收货7天或15天禁止退换货之后结算）
	async received() {
		let response = {
			code: 1,
		};
		const start = Date.now();
		const nowdate = start;

		const {
			order_id,
			state
		} = this.ctx.data;
		// console.log('this.ctx.data', this.ctx.data);
		let uid = '';
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
			}
		}

		let where_obj = {
			is_delete: 0,
			create_uid: uid,
			order_id: order_id
		};

		let orderRes = await this.db.collection('wmzmall-order')
			.where(where_obj)
			.field({
				order_actural_paid: true,
				order_id: true,
				is_fxs: true,
				is_settlement: true,
				order_fxs_uid: true,
				order_fxs_amount: true,
				order_fxs_uid2: true,
				order_fxs_amount2: true,
				order_member_name: true,
				order_member_openid: true,
				order_member_headimg: true,
				order_info: true,
				order_goods_cnt: true,
				create_uid: true,
			})
			.get();

		if (!(orderRes && orderRes.data && orderRes.data.length == 1)) {
			uniCloud.logger.info(`订单[${order_id}]不存在`);
			return response;
		}
		const order = orderRes.data[0];

		let orderUpdate = {
			state: state,
			// 收货时间
			received_time: nowdate,

			last_modify_time: nowdate,
			last_modify_uid: uid
		};
		// 分销订单
		if (order.is_fxs == '是' && order.is_settlement == '否') {
			if (order.order_fxs_uid && order.order_fxs_amount) {
				// 1. 分销商可提现金额
				await this.db.collection('wmzmall-distributor').doc(order.order_fxs_uid).update({
					fxs_unsettled_amount: this.db.command.inc(-order.order_fxs_amount),
					fxs_cashout_amount: this.db.command.inc(order.order_fxs_amount),
					version: this.db.command.inc(1),

					last_modify_uid: uid,
					last_modify_time: nowdate
				});
				// 2. 分销记录状态 已结算
				await this.db.collection('wmzmall-distributor-record').where({
					fxs_uid: order.order_fxs_uid,
					order_id: order.order_id
				}).update({
					version: this.db.command.inc(1),
					state: '已结算',

					last_modify_uid: uid,
					last_modify_time: nowdate
				});

				// 3. 分销操作日志
				await this.db.collection('wmzmall-distributor-log').add({
					fxs_uid: order.order_fxs_uid,
					oper_content: `结算订单[+${order.order_id}]收益`,
					oper_type: '下单收益',
					oper_ip: this.ctx.context.CLIENTIP,
					remark: `下级会员[${order.order_member_name}]下单[+${order.order_fxs_amount / 100}]`,
					version: 1,
					is_delete: 0,
					create_uid: uid,
					create_time: nowdate
				});
			}

			if (order.order_fxs_uid2 && order.order_fxs_amount2) {
				// 1. 上上级分销商可提现金额
				await this.db.collection('wmzmall-distributor').doc(order.order_fxs_uid2).update({
					fxs_unsettled_amount: this.db.command.inc(-order.order_fxs_amount2),
					fxs_cashout_amount: this.db.command.inc(order.order_fxs_amount2),
					version: this.db.command.inc(1),

					last_modify_uid: uid,
					last_modify_time: nowdate
				});
				// 2. 上上级分销记录状态 已结算
				await this.db.collection('wmzmall-distributor-record').where({
					fxs_uid: order.order_fxs_uid2,
					order_id: order.order_id
				}).update({
					version: this.db.command.inc(1),
					state: '已结算',

					last_modify_uid: uid,
					last_modify_time: nowdate
				});

				// 3. 上上级分销操作日志
				await this.db.collection('wmzmall-distributor-log').add({
					fxs_uid: order.order_fxs_uid2,
					oper_content: `结算订单[+${order.order_id}]收益`,
					oper_type: '下单收益',
					oper_ip: this.ctx.context.CLIENTIP,
					remark: `下下级会员[${order.order_member_name}]下单[+${order.order_fxs_amount2 / 100}]`,
					version: 1,
					is_delete: 0,
					create_uid: uid,
					create_time: nowdate
				});
			}

			// 4. 分销订单已结算
			orderUpdate.is_settlement = '是';
			orderUpdate.settlement_time = nowdate;
		}

		const orderUpdateRes = await this.db.collection('wmzmall-order')
			.doc(order._id)
			.update(orderUpdate);

		if (orderUpdateRes && orderUpdateRes.updated == 1) {
			const order_log = {
				order_id: order_id,
				log_type: '已收货',
				current_state: state,
				prev_state: '待收货',
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			};
			await this.db.collection('wmzmall-order-log').add(order_log);
		}

		response.datas = orderUpdateRes;

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}

	// 删除订单
	async deleted() {
		let response = {
			code: 1,
		};
		const state = '已删除'
		const start = Date.now();
		const {
			order_id,
		} = this.ctx.data;
		let uid = '';
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
			}
		}
		let where_obj = {
			create_uid: uid,
			order_id: order_id,
			state: '已取消'
		};

		let orderRes = await this.db.collection('wmzmall-order')
			.where(where_obj)
			.update({
				state: state,

				is_delete: 1,
				last_modify_time: Date.now(),
				last_modify_uid: uid,
			})

		if (orderRes && orderRes.updated == 1) {
			let order_log = {
				order_id: order_id,
				log_type: '删除订单',
				current_state: state,
				prev_state: '已取消',
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: Date.now()
			};
			await this.db.collection('wmzmall-order-log').add(order_log);
		}

		response.datas = orderRes;

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}
	// 订单评价
	async evaluate() {
		let response = {
			code: 1
		};

		const start = Date.now();
		const nowdate = start;
		const {
			order_id,
			review_cnt,
			review_imgs,
			review_type,
			review_content,
			review_anonymity
		} = this.ctx.data

		// 验证评价请求数据
		await this.validateEvaluate(this.ctx.data);

		let uid = '';
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}
		let where_obj = {
			is_delete: 0,
			order_id: order_id,
			state: '待评价',
			create_uid: uid,
		};

		const orderRes = await this.db.collection('wmzmall-order')
			.where(where_obj)
			.get();

		if (!(orderRes.data && orderRes.data.length == 1)) {
			response.msg = '待评价订单不存在';
			return response;
		}

		const order = orderRes.data[0];
		const orderDetailRes = await this.db.collection('wmzmall-order-detail').where({
			order_id: order_id
		}).get();

		// 开始事务
		const dbtran = await this.db.startTransaction();
		try {
			// 记录订单日志
			await dbtran.collection('wmzmall-order-log').add({
				order_id: order_id,
				log_type: '评价订单',
				current_state: '已完成',
				prev_state: order.state,
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			});
			// 修改订单状态 已完成
			await dbtran.collection('wmzmall-order').doc(order._id).update({
				state: '已完成',

				last_modify_time: nowdate,
				last_modify_uid: uid
			});
			uniCloud.logger.info('orderDetailRes', orderDetailRes);
			if (orderDetailRes.data && orderDetailRes.data.length > 0) {
				let detail;
				for (let i = 0; i < orderDetailRes.data.length; i++) {
					detail = orderDetailRes.data[i];
					await dbtran.collection('wmzmall-goods-comment').add({
						goods_id: detail.goods_id,
						goods_sku: detail.goods_sku,
						goods_type: detail.goods_type,
						member_name: order.order_member_name,
						member_headimg: order.order_member_headimg,
						order_id: order_id,
						review_type: review_type,
						review_cnt: review_cnt,
						review_content: review_content,
						review_imgs: review_imgs,
						review_anonymity: review_anonymity,
						remark: "",
						state: "显示",
						version: 1,
						is_delete: 0,
						create_uid: uid,
						create_time: nowdate
					});
				}
			}

			// 提交事务
			await dbtran.commit();
		} catch (e) {
			// 回滚事务
			await dbtran.rollback();
			response.msg = e.message;
			return response
		}


		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.time = `耗时：${end - start}ms`;
		response.msg = '提交成功';
		return response;
	}
	// 验证评价内容
	async validateEvaluate(req) {
		if (!req) this.throw('请求参数不存在');
		if (!req.order_id) this.throw('待评价订单不存在');
		if (!(req.review_content || (req.review_imgs && req.review_imgs.length > 0))) this.throw('请填写评价内容或图片');


		const uCheck = new UniSecObj({
			provider: 'mp-weixin'
		});

		// 文字内容安全检测 
		if (req.review_content) {
			let txtRes = await uCheck.textSecCheck({
				content: req.review_content
			});
			uniCloud.logger.info('txtRes', txtRes);
			if (txtRes.errCode) {
				txtRes.type = '文字';
				this.throw(txtRes);
			}
		}

		// 图片内容安全检测
		if (req.review_imgs && req.review_imgs.length > 0) {
			for (let i = 0; i < req.review_imgs.length; i++) {
				let imgRes = await uCheck.imgSecCheck({
					image: req.review_imgs[i]
				});
				uniCloud.logger.info('imgRes', imgRes);
				if (imgRes.errCode) {
					imgRes.idx = idx;
					imgRes.type = '图片';
					this.throw(imgRes);
				}
			}
		}
	}

	// 订单评价 V2
	// 单个商品分别评价模式
	async evaluateV2() {
		let response = {
			code: 1
		};

		const start = Date.now();
		const nowdate = start;
		const {
			order_id,
			datas
		} = this.ctx.data

		// 验证评价请求数据
		await this.validateEvaluates(datas);

		let uid = '';
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}
		let where_obj = {
			is_delete: 0,
			order_id: order_id,
			state: '待评价',
			create_uid: uid,
		};

		const orderRes = await this.db.collection('wmzmall-order')
			.where(where_obj)
			.get();

		if (!(orderRes.data && orderRes.data.length == 1)) {
			response.msg = '待评价订单不存在';
			return response;
		}

		const order = orderRes.data[0];
		const orderDetailRes = await this.db.collection('wmzmall-order-detail').where({
			order_id: order_id
		}).get();

		// 开始事务
		const dbtran = await this.db.startTransaction();
		try {
			// 记录订单日志
			await dbtran.collection('wmzmall-order-log').add({
				order_id: order_id,
				log_type: '评价订单',
				current_state: '已完成',
				prev_state: order.state,
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			});
			// 修改订单状态 已完成
			await dbtran.collection('wmzmall-order').doc(order._id).update({
				state: '已完成',

				last_modify_time: nowdate,
				last_modify_uid: uid
			});
			uniCloud.logger.info('orderDetailRes', orderDetailRes);
			if (orderDetailRes.data && orderDetailRes.data.length > 0) {
				let detail,
					reviewData;
				for (let i = 0; i < orderDetailRes.data.length; i++) {
					detail = orderDetailRes.data[i];

					reviewData = datas.find(x => x._id == detail._id);
					if (reviewData && reviewData._id) {
						if (reviewData.review_anonymity) {
							// 脱敏处理
							reviewData.member_name = this.service.utils.desz(order.order_member_name);
							reviewData.member_headimg = '';
						}
						delete reviewData._id;

						await dbtran.collection('wmzmall-goods-comment').add({
							goods_id: detail.goods_id,
							goods_sku: detail.goods_sku,
							goods_type: detail.goods_sku_name,
							member_name: order.order_member_name,
							member_headimg: order.order_member_headimg,
							order_id: order_id,

							remark: "",
							state: "显示",
							version: 1,
							is_delete: 0,
							create_uid: uid,
							create_time: nowdate,

							...reviewData
						});
					}
				}
			}

			// 提交事务
			await dbtran.commit();
		} catch (e) {
			// 回滚事务
			await dbtran.rollback();
			response.msg = e.message;
			return response
		}


		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.time = `耗时：${end - start}ms`;
		response.msg = '提交成功';
		return response;
	}
	// 验证评价内容
	async validateEvaluates(datas) {
		if (!(datas && datas.length)) this.throw('提交评价项不存在');

		const uCheck = new UniSecObj({
			provider: 'mp-weixin'
		});

		for (let i = 0; i < datas.length; i++) {
			let req = datas[i];

			if (!req) this.throw(`[商品 ${i+1}]的请求参数不存在`);
			if (!(req.review_content || (req.review_imgs && req.review_imgs.length > 0))) this.throw(
				`请填写[商品 ${i+1}]的评价内容或图片`);

			// 文字内容安全检测 
			if (req.review_content) {
				let txtRes = await uCheck.textSecCheck({
					content: req.review_content
				});
				uniCloud.logger.info('txtRes', txtRes);
				if (txtRes.errCode) {
					txtRes.type = `[商品 ${i+1}]的文字`;
					this.throw(txtRes);
				}
			}

			// 图片内容安全检测
			if (req.review_imgs && req.review_imgs.length) {
				for (let idx = 0; idx < req.review_imgs.length; idx++) {
					let imgRes = await uCheck.imgSecCheck({
						image: req.review_imgs[idx]
					});
					uniCloud.logger.info('imgRes', imgRes);
					if (imgRes.errCode) {
						imgRes.idx = idx;
						imgRes.type = `[商品 ${i+1}]的图片`;
						this.throw(imgRes);
					}
				}
			}
		}
	}

	// 申请退款
	async refund() {
		let response = {
			code: 1
		};

		const start = Date.now();
		const {
			order_id,
			refund_money,
			goods_state,
			reason,
			desc,
			imgs
		} = this.ctx.data

		if (!reason.trim()) {
			response.msg = '请输入退款原因';
			return response;
		}
		if (!order_id.trim()) {
			response.msg = '申请退款订单不存在';
			return response;
		}

		let uid = '';
		let app_id
		let shop_id
		let user = {
			openid: '',
			name: '',
			headimg: '',
			mobile: ''
		};
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
				if (userRes.userInfo.wx_openid) {
					user.openid = userRes.userInfo.wx_openid['mp-weixin'];
				}
				user.name = userRes.userInfo.username || userRes.userInfo.nickname;
				user.headimg = userRes.userInfo.avatar;
				user.mobile = userRes.userInfo.mobile || '';
				user.app_id = userRes.userInfo.app_id;
				user.shop_id = userRes.userInfo.shop_id;
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}

		let where_obj = {
			is_delete: 0,
			order_id: order_id,
			state: '待发货',
			create_uid: uid,
		};

		let orderRes = await this.db.collection('wmzmall-order')
			.where(where_obj)
			.get();

		if (!(orderRes.data && orderRes.data.length == 1)) {
			response.msg = '申请退款订单号不存在';
			return response;
		}

		const order = orderRes.data[0];

		let order_log = {
			order_id: order_id,
			log_type: '申请退款',
			current_state: '售后中',
			prev_state: order.state,
			ip: this.ctx.context.CLIENTIP,
			is_delete: 0,
			create_uid: uid,
			create_time: Date.now(),
			create_uname: user.name
		};

		// todo 开启事务

		// 写入订单日志
		await this.db.collection('wmzmall-order-log').add(order_log);
		// 修改订单申请退款数据
		await this.db.collection('wmzmall-order').doc(order._id).update({
			order_refund_state: '处理中',
			order_refund_reason: reason,
			order_refund_desc: desc,

			state: '售后中',

			last_modify_time: Date.now(),
			last_modify_uid: uid,
			last_modify_uname: user.name
		});
		// 写入申请退款数据
		await this.db.collection('wmzmall-order-refund').add({
			order_id,
			refund_money,
			member_guid: uid,
			member_name: user.name,
			member_headimg: user.headimg,
			goods_state,
			reason,
			desc,
			imgs,
			remark: '申请退款',
			version: 1,
			state: '处理中',
			is_delete: 0,
			create_uid: uid,
			create_time: Date.now(),
			create_uname: user.name,
			app_id: app_id,
			shop_id: shop_id
		});

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.time = `耗时：${end - start}ms`;
		response.msg = '申请成功';
		return response;
	}

	// 支付下单
	async pay() {
		let response = {
			code: 1,
		};

		const start = Date.now();
		const nowdate = start;
		const {
			code,
			order_id,
			pay_way,
			pay_original,
			pay_trade_type,
		} = this.ctx.data;

		// 1. 查询当前订单是否存在，是否已支付待核实状态
		// 2. 查询当前订单支付状态是否为已付款
		// 3. 判断下单商品的状态与库存
		const {
			uid,
			app_id,
			openid,
			order,
			orderDetails,
			pay
		} = await this.payValidate(order_id);
		// 4. 根据支付方式获取对应 code 的 openid 
		// 5. 根据支付方式获取对应的下单数据

		let payres = '';
		let paypreid = '';
		let orderInfo = {};
		// 确保每次支付交易单号唯一
		let out_trade_no = `${order_id}_${(Math.floor(Math.random() * 1000000) + "").padStart(6, '0')}`;
		switch (pay_way) {
			case '微信支付':
				let wxpayOrderInfo = {};
				// 剩余时间
				let time_remaining = (order.order_expire_time - Date.now()) / 1000;
				switch (pay_trade_type) {
					case 'APP': // APP
					case 'MWEB': // H5 微信外部浏览器
					case 'H5WX': // H5 微信公众号（内部浏览器）
					case 'NATIVE': // 二维码
					default: // 小程序微信支付
						wxpayOrderInfo = await this.service.wechat.pay(app_id, openid, out_trade_no, order
							.order_actural_paid, order.order_info, "/notify/wxpay-app")
						wxpayOrderInfo = wxpayOrderInfo.data
						break;
				}
				// 下单支付参数
				orderInfo = wxpayOrderInfo;

				paypreid = wxpayOrderInfo.prepayId;
				payres = JSON.stringify(wxpayOrderInfo);
				break;
			case '支付宝':
				let alipayOrderInfo

				switch (pay_trade_type) {
					case 'APP':
						alipayOrderInfo = await this.service.alipay.payApp(app_id, openid, out_trade_no, order
							.order_actural_paid, order.order_info, "/notify/alipay-app")
						// 下单支付参数
						orderInfo = {
							trade_no: alipayOrderInfo.data
						};
						break;
					default: // 小程序支付宝支付
						alipayOrderInfo = await this.service.alipay.pay(app_id, openid, out_trade_no, order
							.order_actural_paid, order.order_info, "/notify/alipay-app")
						// 下单支付参数
						orderInfo = {
							trade_no: alipayOrderInfo.data
						};
						break;
				}
				paypreid = alipayOrderInfo.data;
				payres = JSON.stringify(alipayOrderInfo);
				break;
			case '百度钱包':
				break;
			case 'QQ钱包':
				break;
			case '头条支付':
				break;
			case '余额支付':
				break;
			default:
				break;
		}

		if (pay && pay._id) {
			// 修改 wmzmall-order-pay 数据
			await this.db.collection('wmzmall-order-pay').doc(pay._id).update({
				pay_way: pay_way,
				pay_original: pay_original,
				pay_trade_type: pay_trade_type,
				out_trade_no: out_trade_no,

				pay_openid: openid,
				pay_preid: paypreid,
				pay_res: payres,
				version: this.db.command.inc(1)
			});
		} else {
			let order_pay = {
				order_id: order_id,
				out_trade_no: out_trade_no,
				pay_openid: openid,
				pay_way: pay_way,
				pay_original: pay_original,
				pay_trade_type: pay_trade_type,
				pay_preid: paypreid,
				pay_res: payres,
				pay_state: '待付款',
				version: 1,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			};
			await this.db.collection('wmzmall-order-pay').add(order_pay);
		}

		// 返回下单数据
		orderInfo.order_id = order_id;
		orderInfo.out_trade_no = out_trade_no;
		response.datas = orderInfo;

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.code = 0;
		response.duration = `耗时：${end - start}ms`;
		return response;
	}

	// 支付下单验证
	async payValidate(order_id) {
		// 1. 查询当前订单是否存在，是否已支付待核实状态
		// 2. 查询当前订单支付状态是否为已付款
		// 3. 判断下单商品的状态与库存

		if (!order_id) {
			this.throw('订单编号不存在');
		}

		let uid = '';
		let app_id
		let openid
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			console.log(userRes)
			if (userRes.code == 0) {
				uid = userRes.uid;
				app_id = userRes.userInfo.app_id
				openid = userRes.userInfo.openid
			}
		}
		if (!uid) {
			this.throw('当前未登录');

		}
		// 1. 查询当前订单是否存在，是否已支付待核实状态
		const orderRes = await this.db.collection('wmzmall-order')
			.where({
				order_id
			})
			.field({
				app_id: true,
				order_id: true,
				order_actural_paid: true,
				order_info: true,
				state: true,
				order_pay_state: true,
				create_uid: true,
				create_time: true,
				order_expire_time: true
			})
			.get();
		if (!(orderRes && orderRes.data.length == 1)) {
			this.throw('订单不存在');
		}

		const order = orderRes.data[0];
		if (order.create_uid != uid) {
			this.throw('订单与当前账号不一致');
		}
		if (order.state != '待付款') {
			this.throw(`订单[${order_id}]状态[${order.state}]`);
		}
		if (order.order_pay_state == '待核实') {
			this.throw(`订单状态为已支付待核实，请勿需再次付款`);
		}

		// 订单详情
		const orderDetailRes = await this.db.collection('wmzmall-order-detail')
			.where({
				order_id
			})
			.field({
				goods_id: true,
				order_id: true,
				goods_num: true,
				goods_sku: true,
				goods_sku_id: true
			})
			.get();
		if (!(orderDetailRes && orderDetailRes.data.length > 0)) {
			this.throw('订单详情不存在');
		}
		const orderDetails = orderDetailRes.data;

		// 2. 查询当前订单支付状态是否为已付款
		const payRes = await this.db.collection('wmzmall-order-pay')
			.where({
				order_id
			})
			.field({
				order_id: true,
				out_trade_no: true,
				pay_way: true,
				pay_trade_type: true,
				pay_state: true,
				pay_res: true,
				create_time: true
			})
			.get();

		let pay = {};
		if (payRes.data && payRes.data.length) {
			pay = payRes.data[0];
			if (pay.pay_state == '已付款') {
				this.throw(`订单[${order_id}]已付款，无需重新支付`);
			}

			/* let uniPayIns;
			// 判断是否存在重复支付，存在则关闭订单
			if (pay.pay_way == '微信支付') {
				let wxpayConfig;
				if (pay.pay_trade_type == 'APP') { // APP 微信支付
					wxpayConfig = uidObj.config['app-plus']['wxpay'];
				} else if (pay.pay_trade_type == 'H5WX') { // 微信公众号 微信支付
					wxpayConfig = uidObj.config['h5-weixin']['pay'];
				} else { // 微信小程序 微信支付
					wxpayConfig = uidObj.config['mp-weixin']['pay'];
				}
				// 初始化微信支付
				uniPayIns = uidPay.initWeixin(wxpayConfig);
			} else if (pay.pay_way == '支付宝') {
				// 初始化支付宝支付
				let alipayConfig = uidObj.config['mp-alipay']['pay'];
				if (pay.pay_trade_type == 'APP') {
					alipayConfig = uidObj.config['app-plus']['alipay'];
				}

				// 初始化支付宝支付
				uniPayIns = uidPay.initAlipay(alipayConfig);
			}

			// 关闭订单
			if (uniPayIns) {
				let closeRes = await uniPayIns.closeOrder({
					outTradeNo: pay.out_trade_no || pay.order_id
				});
				console.log('closeOrder res', closeRes);
			} */
		}
		const goodsIds = orderDetails.map(x => x.goods_id);
		const goodsSkus = orderDetails.filter(x => x.goods_sku).map(x => x.goods_sku);
		// 下单商品
		const goodsRes = await this.db.collection('wmzmall-goods')
			.where({
				_id: dbcmd.in(goodsIds)
			})
			.field({
				stock_num: true,
				name: true,
				state: true
			})
			.get();
		if (!(goodsRes && goodsRes.data.length > 0)) {
			this.throw('下单商品不存在');
		}

		const goodsDatas = goodsRes.data;
		let goodsSkuDatas = [];

		if (goodsSkus.length) {
			// 下单SKU商品
			const goodsSkuRes = await this.db.collection('wmzmall-goods-sku')
				.where({
					goods_id: dbcmd.in(goodsIds),
					goods_sku: dbcmd.in(goodsSkus)
				})
				.field({
					stock_num: true,
					goods_id: true,
					goods_sku: true
				})
				.get();
			if (!(goodsSkuRes.data && goodsSkuRes.data.length)) {
				this.throw('下单SKU商品不存在');
			}

			goodsSkuDatas = goodsSkuRes.data;
		}

		// 3. 判断下单商品的状态与库存
		orderDetails.forEach((x) => {
			// 下单商品
			let goods = goodsDatas.find(g => g._id == x.goods_id);
			if (!goods) {
				this.throw('下单商品已下架');
			}
			if (goods.state != '销售中') {
				this.throw(`下单商品[${goods.state}]`);
			}

			if (x.goods_sku) {
				// 下单SKU商品
				let goodsSku = goodsSkuDatas.find(g => g.goods_id == x.goods_id && g.goods_sku == x
					.goods_sku);
				if (!goodsSku) {
					this.throw('下单SKU商品已下架');
				}
				// 判断SKU库存是否充足
				if (goodsSku.stock_num <= 0) {
					this.throw(`SKU商品库存不足`);
				}
				if (goodsSku.stock_num < x.goods_num) {
					this.throw(`SKU商品剩余库存 ${goodsSku.stock_num}`);
				}
			} else {
				if (goods.stock_num <= 0) {
					this.throw(`商品库存不足`);
				}
				if (goods.stock_num < x.goods_num) {
					this.throw(`商品剩余库存 ${goods.stock_num}`);
				}
			}
		});

		return {
			uid,
			app_id,
			openid,
			order,
			orderDetails,
			pay
		};
	}


	// 支付状态查询
	async paystate() {
		let response = {
			code: 1,
			msg: '支付状态查询失败'
		};

		const {
			order_id
		} = this.ctx.data;

		if (!order_id) {
			response.msg = '订单号不存在';
			return response;
		}

		// 查询订单支付状态
		const payRes = await this.db.collection('wmzmall-order-pay').where({
			order_id
		}).get();
		if (!payRes || payRes.data.length !== 1) {
			response.msg = '支付单不存在';
			return response;
		}

		const payObj = payRes.data[0];
		if (payObj.pay_state == '已付款') {
			response.code = 0;
			response.datas = {
				pay_state: payObj.pay_state,
				order_id: payObj.order_id
			};
			return response;
		}

		// 查询微信支付订单状态
		switch (payObj.pay_way) {
			case '微信支付':
				let wxpayConfig;
				if (payObj.pay_trade_type == 'APP') {
					// APP 微信支付
					wxpayConfig = uidObj.config['app-plus']['wxpay'];
				} else if (payObj.pay_trade_type == 'H5WX') {
					// 微信公众号 微信支付
					wxpayConfig = uidObj.config['h5-weixin']['pay'];
				} else {
					// 微信小程序 微信支付
					wxpayConfig = uidObj.config['mp-weixin']['pay'];
				}
				// 初始化微信支付
				const uniWxpayIns = uidPay.initWeixin(wxpayConfig);
				const uniWxpayRes = await uniWxpayIns.orderQuery({
					outTradeNo: payObj.out_trade_no,
				});

				response.code = 0;
				response.datas = {
					pay_state: payObj.pay_state,
					order_id: payObj.order_id,
					trade_state: uniWxpayRes.tradeState
				};
				return response;
			case '支付宝':
				const uniAlipayIns = uidPay.initWeixin(uidObj.config['mp-alipay']['pay']);
				const uniAlipayRes = await uniAlipayIns.orderQuery({
					outTradeNo: payObj.out_trade_no,
				});

				response.code = 0;
				response.datas = {
					pay_state: payObj.pay_state,
					order_id: payObj.order_id,
					trade_state: uniAlipayRes.tradeState
				};
				return response;
		}

		return response;
	}

	// 物流轨迹
	async express() {
		let response = {
			code: 1,
			msg: '物流轨迹查询失败'
		};
		const {
			order_id
		} = this.ctx.data;

		if (!order_id) {
			response.msg = '订单号不存在';
			return response;
		}

		// 查询订单数据
		const orderRes = await this.db.collection('wmzmall-order').where({
			order_id
		}).field({
			order_id: true,
			order_express: true,
			order_express_no: true,
			order_express_datas: true
		}).get();

		if (!orderRes || orderRes.data.length !== 1) {
			response.msg = '订单不存在';
			return response;
		}

		const order = orderRes.data[0];

		// 存在有数据直接返回 express datas
		if (order.order_express_datas) {
			response.msg = '数据查询成功';
			response.code = 0;
			response.datas = order.order_express_datas;
			response.datas.company = order.order_express;

			return response;
		}

		if (!order.order_express_no) {
			response.msg = '快递单号不存在';

			return response;
		}

		// 调用快递100 实时快递查询接口
		const kd100Res = await this.service.express.kd100Query({
			"com": this.service.express.getKd100Com(order.order_express),
			"num": order.order_express_no,
		});
		response.datas = kd100Res;
		response.msg = response.datas.message;

		if (response.datas && response.datas.message == "ok") {
			response.code = 0;

			/**
			 * 快递单状态
				0	在途	快件处于运输过程中
				1	揽收	快件已由快递公司揽收
				2	疑难	快递100无法解析的状态，或者是需要人工介入的状态， 比方说收件人电话错误。
				3	签收	正常签收
				4	退签	货物退回发货人并签收
				5	派件	货物正在进行派件
				6	退回	货物正处于返回发货人的途中
				7	转投	货物转给其他快递公司邮寄
				10	待清关	货物等待清关
				11	清关中	货物正在清关流程中
				12	已清关	货物已完成清关流程
				13	清关异常	货物在清关过程中出现异常
				14	拒签	收件人明确拒收
			 */
			if (['3', '4', '14'].includes(response.datas.state)) {
				response.datas.company = order.order_express;
				// 签收 退签 拒签
				// 写入订单物流轨迹数据
				await this.db.collection('wmzmall-order').doc(order._id).update({
					order_express_datas: response.datas
				});
			}
		}

		return response;
	}

	// 创建订单
	async create() {
		// 判断是否登录
		// 判断收货人是否存在
		// 判断下单来源 (1.从商品详情下单 2.从购物车下单)
		// 	判断商品是否存在
		// 	判断商品状态是否为 销售中
		// 	判断商品库存是否满足下单数
		// 	判断购物车商品是否存在
		// 	判断购物车商品状态是否为 销售中
		// 	判断购物车商品库存是否满足下单数
		// [新增]取付费会员商品会员价
		// 写入订单数据并记录分销数据
		// 根据订单设置,如果为下单成功后扣减库存,则扣减对应商品扣除
		// 写入订单详情数据
		// 写入订单支付数据
		// 写入订单日志

		let response = {
			code: 1,
			goods: {},
			goods_detail: {},
			goods_skus: []
		};

		const start = Date.now();
		const nowdate = start;

		let uid = '';
		let shop_id
		let user = {
			openid: '',
			name: '',
			headimg: '',
			mobile: ''
		};
		if (this.ctx.event.uniIdToken) {
			// 已登录，获取当前登录 uid
			const userRes = await uidObj.checkToken(this.ctx.event.uniIdToken);
			if (userRes.code == 0) {
				uid = userRes.uid;
				if (userRes.userInfo.wx_openid) {
					user.openid = userRes.userInfo.wx_openid['mp-weixin'];
				} else {
					user.openid = userRes.userInfo.openid
				}
				user.name = userRes.userInfo.username || userRes.userInfo.nickname;
				user.headimg = userRes.userInfo.avatar;
				user.mobile = userRes.userInfo.mobile || '';
				shop_id = userRes.userInfo.shop_id
			}
		}
		if (!uid) {
			response.msg = '当前未登录'
			return response;
		}
		if (!shop_id) {
			response.msg = '门店ID为空'
			return response;
		}
		const {
			cart_ids,
			sharemid,
			goods_id,
			goods_num,
			goods_sku_id,
			order_coupon_id,
			addr_id,
			order_from,
			order_desc
		} = this.ctx.data;

		const memberRes = await this.db.collection('wmzmall-member').doc(uid)
			.field({
				member_session_key: false,
				member_password: false
			}).get();

		let memberData = {};
		if (memberRes && memberRes.data.length === 1) {
			memberData = memberRes.data[0];
			if (!memberData.myfxs_uid && sharemid && sharemid != uid) {
				// 修改下单者的 分销商
				console.log('修改下单者的 分销商', memberData, sharemid);
				await this.db.collection('wmzmall-member').doc(uid).update({
					myfxs_uid: sharemid,
					myfxs_time: nowdate,
					myfxs_source: 'order'
				});
				await this.db.collection('wmzmall-distributor').doc(uid).update({
					fxs_member_cnt: dbcmd.inc(1)
				});
				memberData.myfxs_uid = sharemid;
			}

			// 已付费有效期内的会员
			memberData.vip = memberData.is_plus === '付费会员' && memberData.plus_time >= Date.now();
		}

		const addrRes = await this.db.collection('wmzmall-member-address').doc(addr_id).get();
		if (!(addrRes && addrRes.data.length === 1)) {
			response.msg = '请选择收货人';
			return response;
		}
		const addr = addrRes.data[0];
		if (addr.create_uid != uid) {
			response.msg = '收货人与当前账号不一致';
			return response;
		}

		let goods = [];
		let goodsData = {};
		let preOrder = {};

		// 购物车 ID 集合
		let goodsCartIds = [];
		if (goods_id) {
			// 从商品详情页下单
			let goodsRes = await this.db.collection('wmzmall-goods').doc(goods_id).get();
			if (!(goodsRes && goodsRes.data.length == 1)) {
				response.msg = '当前下单商品不存在';
				return response;
			}
			goodsData = goodsRes.data[0];
			let goodsState = goodsData.state;
			if (goodsState != '销售中') {
				switch (goodsState) {
					case '待审核':
						response.msg = `当前商品未开售`;
						break;
					case '已下架':
					default:
						response.msg = `当前商品${goodsState}`;
						break;
				}
				return response;
			}

			// 下单数量
			goodsData.goods_num = goods_num || 1;

			if (goods_sku_id) {
				// 商品存在 sku
				let skuRes = await this.db.collection('wmzmall-goods-sku').doc(goods_sku_id).get();
				if (skuRes && skuRes.data.length == 1) {
					let goodsSku = skuRes.data[0];
					// 存在 sku 修改商品价格、库存
					goodsData.stock_num = goodsSku.stock_num;
					goodsData.price = goodsSku.price;
					goodsData.vip_price = goodsSku.vip_price;
					goodsData.market_price = goodsSku.market_price;
					goodsData.sku = goodsSku.goods_sku;
					goodsData.sku_id = goodsSku._id;
					goodsData.sku_name = [goodsSku.sku1_spec, goodsSku.sku2_spec, goodsSku.sku3_spec, goodsSku
						.sku4_spec
					].filter(s => s).join(' & ');
					goodsData.sku_img = goodsSku.img;
					goodsData.sku_price = goodsSku.price;
					goodsData.sku_market_price = goodsSku.market_price;
				}
			}

			goods.push(goodsData);

			// 判断库存是否满足下单数
			if (goodsData.stock_num < goods_num) {
				response.msg = `当前商品库存数不足`;
				return response;
			}

		} else if (cart_ids && cart_ids.length > 0) {
			// 从购物车下单
			let goodsCartRes = await this.db.collection('wmzmall-goods-cart').where({
				create_uid: uid,
				_id: dbcmd.in(cart_ids)
			}).get();
			if (!(goodsCartRes && goodsCartRes.data.length > 0)) {
				response.msg = '当前购物车不存在';
				return response;
			}
			let goodsCarts = goodsCartRes.data;
			goodsCartIds = goodsCarts.map(x => x._id);
			let goodsIds = goodsCarts.map(x => x.goods);
			let goodsSkuIds = goodsCarts.map(x => x.goods_sku);

			let goodsRes = await this.db.collection('wmzmall-goods').where({
				_id: dbcmd.in(goodsIds),
				state: '销售中'
			}).get();
			if (!(goodsRes && goodsRes.data.length > 0)) {
				response.msg = '当前购物车商品不存在';
				return response;
			}
			let goodsDatas = goodsRes.data;
			let goodsSkus = [];
			let skuRes = await this.db.collection('wmzmall-goods-sku').where({
				_id: dbcmd.in(goodsSkuIds)
			}).get();
			if (skuRes && skuRes.data.length > 0) {
				goodsSkus = skuRes.data;
			}

			goodsCarts.forEach((x, idx) => {
				// 进行深拷贝，防止同一sku产品 堆属性引用值 数据
				goodsData = JSON.parse(JSON.stringify(goodsDatas.find(g => g._id == x.goods)));
				// 购物车商品数量
				goodsData.goods_num = x.goods_num;

				let goodsSku = goodsSkus.find(g => g._id == x.goods_sku && g.goods_id == x.goods);

				if (goodsSku && goodsSku._id) {
					goodsData.stock_num = goodsSku.stock_num;
					goodsData.price = goodsSku.price;
					goodsData.vip_price = goodsSku.vip_price;
					goodsData.market_price = goodsSku.market_price;
					goodsData.sku = goodsSku.goods_sku;
					goodsData.sku_id = goodsSku._id;
					goodsData.sku_name = [goodsSku.sku1_spec, goodsSku.sku2_spec, goodsSku.sku3_spec,
						goodsSku.sku4_spec
					].filter(s => s).join(' & ');
					goodsData.sku_img = goodsSku.img;
					goodsData.sku_price = goodsSku.price;
					goodsData.sku_market_price = goodsSku.market_price;
				}
				// 下单商品
				goods.push(goodsData);
			});
		}

		if (goods.length <= 0) {
			response.msg = `下单商品不存在`;
			return response;
		}
		const utc8date = this.service.utils.toDateUTC8(Date.now());
		let order = {
			order_id: Date.now() + (Math.round(Math.random() * 1000000) + '').padStart(6, '0'),
			order_member_openid: user.openid,
			order_member_name: user.name,
			order_member_headimg: user.headimg,
			order_member_mobile: user.mobile,
			order_consignee: addr.consignee,
			order_consignee_tel: addr.mobile,
			order_consignee_addr: addr.address,
			order_consignee_addr_detail: addr.addr_detail,
			order_consignee_province_name: addr.province_name,
			order_consignee_city_name: addr.city_name,
			order_consignee_district_name: addr.area_name,
			order_express: '',
			order_express_no: '',
			order_pay_state: '待付款',
			order_total_money: 0,
			order_total_cnt: goods.length,
			order_goods_cnt: 0,
			order_sku_cnt: 0,
			order_discount: 0,
			order_tax: 0,
			order_actural_paid: 0,
			order_from: order_from,
			order_type: '发货订单',
			order_way: '小程序',
			order_info: '',
			remark: order_desc,
			// 分销
			is_fxs: '否',
			is_settlement: '否',
			order_fxs_uid: memberData.myfxs_uid,
			order_fxs_amount: 0,
			order_share_member_id: sharemid,
			state: '待付款',
			self_pick: self_pick,
			yy_mm: this.service.utils.formatdate(utc8date, 'yyyy年MM月'),
			yy_mm_dd: this.service.utils.formatdate(utc8date, 'yyyy年MM月dd日'),
			is_delete: 0,
			create_uid: uid,
			create_time: nowdate,
			create_time_format: this.service.utils.formatdate(utc8date, 'yyyy-MM-dd hh:mm:ss')
		};

		// 下单所得积分
		let integral_total = 0;
		let order_detail = {};
		let order_details = [];
		goods.forEach(x => {

			// 已省金额
			let economize_amount = 0;
			// vip付费会员
			if (memberData.vip) {
				if (x.is_vip === '是') {
					x.market_price = x.price;
					x.price = x.vip_price;

					economize_amount = x.market_price - x.price;
				}
			}

			order_detail = {
				order_id: order.order_id,
				goods_id: x._id,
				goods_name: x.name,
				goods_name_pw: x.name_pw,
				goods_img: x.img,
				goods_num: x.goods_num,
				goods_price: x.price,
				goods_market_price: x.market_price,
				goods_type: x.goods_type || '',
				goods_sku: x.goods_sku || '',
				goods_sku_name: x.sku_name || '',
				goods_sku_img: x.sku_img || x.img,
				goods_sku_id: x.sku_id || '',
				economize_amount: economize_amount,
				is_vip: memberData.vip ? x.is_vip : '',
				is_fxs: x.is_fxs,
				rebate_ratio: x.rebate_ratio,
				fxs_amount: 0,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate,
			};

			if (x.is_fxs == '是' && Boolean(memberData.myfxs_uid)) {
				// 返利金额
				order_detail.fxs_amount = x.price * x.goods_num * (x.rebate_ratio / 100);

				order.is_fxs = '是';
				order.order_fxs_amount += order_detail.fxs_amount;
			}

			order.order_sku_cnt += x.goods_num;
			order.order_goods_cnt += x.goods_num;
			order.order_total_money += x.price * x.goods_num;
			order.order_actural_paid += x.price * x.goods_num;
			// 订单支付标题
			order.order_info = x.name;

			order_details.push(order_detail);
		});

		// 优惠券下单
		let coupon = null;
		if (order_coupon_id) {
			order.order_coupon_id = order_coupon_id;
			const couponRes = await this.db.collection('wmzmall-marketing-coupon').doc(order_coupon_id).get();

			if (!(couponRes.data && couponRes.data.length === 1)) {
				response.msg = '使用的优惠券不存在';
				return response;
			}
			coupon = couponRes.data[0];
			if (coupon.member_id !== uid) {
				response.msg = '请选择本人的优惠券';
				return response;
			}
			if (coupon.is_delete !== 0) {
				response.msg = '使用的优惠券已作废';
				return response;
			}
			if (coupon.state !== '已领取') {
				response.msg = `使用的优惠券【${coupon.state}】`;
				return response;
			}
			if (coupon.end_time < Date.now()) {
				response.msg = `使用的优惠券-已过期`;
				return response;
			}
			if (coupon.order_amount > 0 && coupon.order_amount * 100 > order.order_actural_paid) {
				response.msg = `实际支付金额满[${coupon.order_amount}]可使用优惠券`;
				return response;
			}

			// todo 判断优惠券使用范围

			switch (coupon.type) {
				case '满减':
					order.order_discount = coupon.price;
					order.order_actural_paid -= coupon.price;
					break;
				case '折扣':
					order.order_discount = order.order_actural_paid - order.order_actural_paid * coupon.price;
					order.order_actural_paid *= coupon.price / 100;
					break;
			}
			// 使用的优惠券
			order.order_coupon = coupon;
		}

		if (order.order_actural_paid > 0) {
			// 获取会员设置项
			const memberParameter = this.db.collection('wmzmall-member-parameter').where({
				shop_id: shop_id
			}).field({
				desc: false,
				vip_desc: false
			}).get();
			// 获取积分设置项
			const integralParameter = this.db.collection('wmzmall-integral-parameter').where({
				shop_id: shop_id
			}).field({
				integral_desc: false
			}).get();

			const datas = await Promise.all([memberParameter, integralParameter]);

			const memberParameterRes = datas[0];
			const integralParameterRes = datas[1];

			const member_setting = memberParameterRes.data && memberParameterRes.data[0];
			const integral_setting = integralParameterRes.data && integralParameterRes.data[0];

			// 下单返积分
			if (integral_setting && integral_setting.return_integral_ratio > 0) {
				integral_total = parseInt(order.order_actural_paid * (integral_setting.return_integral_ratio /
					100));
			}
			if (memberData.vip && member_setting && member_setting.vip_integral_mul > 0 && integral_total > 0) {
				integral_total *= member_setting.vip_integral_mul;
			}
			order.order_return_integral = integral_total;
		} else {
			order.order_actural_paid = 0;
		}

		// todo: 开启事务

		try {

			if (order.order_actural_paid <= 0) {
				// 修改订单为已付款待发货
				order.state = '待发货';
				order.order_pay_state = '已付款';
			}
			const orderRes = await this.db.collection('wmzmall-order').add(order);
			console.log('orderRes', orderRes);

			if (!(orderRes && orderRes.id)) {
				response.msg = `订单创建失败`;
				uniCloud.logger.error(`订单创建失败`, order);
				console.log(`订单创建失败`, order);
				return response;
			}

			let order_log = {
				order_id: order.order_id,
				log_type: '创建订单',
				current_state: '待付款',
				prev_state: '待付款',
				ip: this.ctx.context.CLIENTIP,
				is_delete: 0,
				create_uid: uid,
				create_time: nowdate
			};
			await this.db.collection('wmzmall-order-detail').add(order_details);
			await this.db.collection('wmzmall-order-log').add(order_log);

			if (order.order_actural_paid <= 0) {
				// 订单日志 待发货
				order_log.log_type = '订单支付';
				order_log.current_state = '待发货';
				order_log.prev_state = '待付款';
				await this.db.collection('wmzmall-order-log').add(order_log);
			}

			// 会员已省金额
			let member_economize = 0;
			// 扣减订单库存
			for (let i = 0; i < order_details.length; i++) {
				let x = order_details[i];
				// 会员已省金额
				member_economize += x.economize_amount;
				// 扣减库存
				// todo 扣减SKU库存
				await this.db.collection('wmzmall-goods')
					.where({
						_id: x.goods_id,
						stock_num: dbcmd.gte(x.goods_num)
					})
					.update({
						stock_num: dbcmd.inc(-x.goods_num),
						sale_cnt: dbcmd.inc(x.goods_num)
					});
			}

			// 删除购物车数据
			if (goodsCartIds.length > 0) {
				await this.db.collection('wmzmall-goods-cart').where({
					_id: dbcmd.in(goodsCartIds)
				}).remove();
			}

			// 已使用优惠券
			if (order_coupon_id && coupon && coupon._id) {
				await this.db.collection('wmzmall-marketing-coupon')
					.doc(order_coupon_id)
					.update({
						last_modify_time: nowdate,
						last_modify_uid: uid,

						order_id: order.order_id,
						version: dbcmd.inc(1),

						state: "已使用"
					});
				await this.db.collection('wmzmall-marketing-coupon-rule')
					.doc(coupon.coupon_id)
					.update({
						use_num: dbcmd.inc(1),
						version: dbcmd.inc(1)
					});
				await this.db.collection('wmzmall-member')
					.doc(uid)
					.update({
						member_coupon_cnt: dbcmd.inc(-1),
						member_economize: dbcmd.inc(member_economize)
					});
			} else {
				await this.db.collection('wmzmall-member')
					.doc(uid)
					.update({
						member_economize: dbcmd.inc(member_economize)
					});
			}

			response.code = 0;
			response.datas = {
				order_id: order.order_id,
				money: order.order_actural_paid,
				vip: memberData.vip
			};

		} catch (e) {

			response.code = 500;
			response.msg = e;

			// 记录日志
			uniCloud.logger.error(e);
			console.log('order/create catch', e);
		}

		const end = Date.now();
		console.log(`耗时：${end - start}ms`);
		response.duration = `耗时：${end - start}ms`;

		return response;
	}

}